使用 Kubernetes 部署API网关Kong
Kong概述:Kong是一个clould-native、快速的、可扩展的、分布式的微服务抽象层(也称为API网关、API中间件或在某些情况下称为服务网格)框架。Kong作为开源项目在2015年推出,它的核心价值是高性能和可扩展性。Kong被广泛用于从初创企业到全球5000家公司以及政府组织的生产环境中。
Kong概述:Kong是一个clould-native、快速的、可扩展的、分布式的微服务抽象层(也称为API网关、API中间件或在某些情况下称为服务网格)框架。Kong作为开源项目在2015年推出,它的核心价值是高性能和可扩展性。Kong被广泛用于从初创企业到全球5000家公司以及政府组织的生产环境中。
如果构建Web、移动或IoT(物联网)应用,可能最终需要使用通用的功能来实现这些应用。Kong充当微服务请求的网关(或侧车),通过插件能够提供负载平衡、日志记录、身份验证、速率限制、转换等能力。
2、功能特性
云本土化(Cloud-Native):Kong可以在Kubernetes或物理环境上运行;
动态负载平衡(Dynamic Load Balancing):跨多个上游服务的负载平衡业务。
基于哈希的负载平衡(Hash-based Load Balancing):一致的散列/粘性会话的负载平衡。
断路器(Circuit-Breaker):智能跟踪不健康的上游服务。
健康检查(Health Checks):主动和被动监控您的上游服务。
服务发现(Service Discovery):解决如Consul等第三方DNS解析器的SRV记录。
无服务器(Serverless):从Kong中直接调用和保证AWS或OpenWhisk函数安全。
WebSockets:通过WebSockets与上游服务进行通信。
OAuth2.0:轻松的向API中添加OAuth2.0认证。
日志记录(Logging):通过HTTP、TCP、UDP记录请求或者相应的日志,存储在磁盘中。
安全(Security):ACL,Bot检测,IPs白名单/黑名单等。
系统日志(Syslog):记录信息到系统日志。
SSL:为基础服务或API设置特定的SSL证书。
监视(Monitoring):能够实时对关键负载和性能指标进行监控。
转发代理(Forward Proxy):使端口连接到中间透明的HTTP代理。
认证(Authentications):支持HMAC,JWT和BASIC方式进行认证等等。
速率限制(Rate-limiting):基于多个变量的阻塞和节流请求。
转换(Transformations):添加、删除或操作HTTP请求和响应。
缓存(Caching):在代理层进行缓存和服务响应。
命令行工具(CLI):能够通过命令行控制Kong的集群。
REST API:可以通过REST API灵活的操作Kong。
GEO复制:在不同的区域,配置总是最新的。
故障检测与恢复(Failure Detection & Recovery):如果Cassandra节点失效,Kong并不会受影响。
群集(Clustering):所有的Kong节点会自动加入群集,并更新各个节点上的配置。
可扩展性(Scalability):通过添加节点,实现水平缩放。
性能(Performance):通过缩放和使用Nigix,Kong能够轻松处理负载。
插件(Plugins):基于插件的可扩展体系结构,能够方便的向Kong和API添加功能。
3、Kong依赖的技术
Kong部署在Nginx和Apache Cassandra或PostgreSQL等可靠技术之上,并提供了易于使用的RESTful API来操作和配置系统。下面是Kong的技术逻辑图。基于这些技术,Kong提供相关的特性支持:
Nginx:
经过验证的高性能基础;
HTTP和反向代理服务器;
处理低层级的操作。
OpenRestry:
支持Lua脚本;
拦截请求/响应生命周期;
基于Nginx进行扩展。
Clustering&Datastore:
支持Cassandra或PostgreSQL数据库;
内存级的缓存;
支持水平扩展。
Plugins:
使用Lua创建插件;
功能强大的定制能力;
与第三方服务实现集成。
Restful Administration API:
通过Restful API管理Kong;
支持CI/CD&DevOps;
基于插件的可扩展。
4、使用Helm在Kubernetes上部署Kong
4.1 前置条件
已有Kubernetes 1.6+环境;
已部署helm客户端和tiller服务端(请参考:https://docs.helm.sh/using_helm/#installing-helm):
在Kubernetes中创建了具备足够权限访问权限的service account;
并通过此service account在Kubernetes部署了tiller服务端(请参考:https://docs.helm.sh/using_helm/#role-based-access-control)。
4.2 Helm char配置
下表列示了Kong chart的配置参数和默认值:
参数 | 说明 | 默认值 |
image.repository | Kong image |
|
image.tag | Kong image version |
|
image.pullPolicy | Image pull policy |
|
image.pullSecrets | Image pull secrets |
|
replicaCount | Kong instance count |
|
admin.useTLS | Secure Admin traffic |
|
admin.servicePort | TCP port on which the Kong admin service is exposed |
|
admin.containerPort | TCP port on which Kong app listens for admin traffic |
|
admin.nodePort | Node port when service type is | |
admin.type | k8s service type, Options: NodePort, ClusterIP, LoadBalancer |
|
admin.loadBalancerIP | Will reuse an existing ingress static IP for the admin service |
|
admin.loadBalancerSourceRanges | Limit admin access to CIDRs if set and service type is |
|
admin.ingress.enabled | Enable ingress resource creation (works with proxy.type=ClusterIP) |
|
admin.ingress.tls | Name of secret resource, containing TLS secret | |
admin.ingress.hosts | List of ingress hosts. |
|
admin.ingress.path | Ingress path. |
|
admin.ingress.annotations | Ingress annotations. See documentation for your ingress controller for details |
|
proxy.useTLS | Secure Proxy traffic |
|
proxy.servicePort | TCP port on which the Kong Proxy Service is exposed |
|
proxy.containerPort | TCP port on which the Kong app listens for Proxy traffic |
|
proxy.nodePort | Node port when service type is | |
proxy.type | k8s service type. Options: NodePort, ClusterIP, LoadBalancer |
|
proxy.loadBalancerSourceRanges | Limit proxy access to CIDRs if set and service type is |
|
proxy.loadBalancerIP | To reuse an existing ingress static IP for the admin service | |
proxy.ingress.enabled | Enable ingress resource creation (works with proxy.type=ClusterIP) |
|
proxy.ingress.tls | Name of secret resource, containing TLS secret | |
proxy.ingress.hosts | List of ingress hosts. |
|
proxy.ingress.path | Ingress path. |
|
proxy.ingress.annotations | Ingress annotations. See documentation for your ingress controller for details |
|
env | Additional Kong configurations | |
runMigrations | Run Kong migrations job |
|
readinessProbe | Kong readiness probe | |
livenessProbe | Kong liveness probe | |
affinity | Node/pod affinities | |
nodeSelector | Node labels for pod assignment |
|
podAnnotations | Annotations to add to each pod |
|
resources | Pod resource requests & limits |
|
tolerations | List of node taints to tolerate |
|
4.3 安装Chart
通过执行如下的命令,在Kubernetes中部署Kong:
$ helm install --name my-release stable/kong
4.4 验证Kong(命令行)
通过执行下面的命令,进入Kong的容器:
kubectl exec -it my-release-kong-d448dc869-fblbk sh
并在kong中执行如下的命令:
curl http://localhost:8001
如果kong正常运行的话,应该会返回一些内容。
4.5 验证Kong(客户端)
另外,也可以安装一个Kong的客户端来验证。在安装有Docker引擎的操作系统上执行如下的命令:
docker run -d -p 8080:8080 pgbi/kong-dashboard start --kong-url http://10.0.32.172:31177
通过docker安装一个Kong-Dashboard,安装完成后,通过浏览器访问:
5、使用
5.1 注册服务
在此部分将会向kong添加一个API,为了做到这一点,首先需要往Kong中添加一个服务。我们将创建一个指向Mockbin API的服务,Mockbin是一个“echo”类型的公共网站,它将返回的请求作为响应返回给请求者。通过此示例有助于了解Kong是如何代理API请求。在开始对服务进行请求之前,需要为服务添加一个路由。路由指定在到达Kong之后如何向服务发送请求,单个服务可以有多个路由。在配置了服务和路由之后,就能够通过Kong对服务进行请求。Kong公开了RESTful Admin API:8001,Kong的配置(包括添加服务和路由)是通过对该API的请求进行的。
5.1.1 注册服务
服务实体是上游服务中的每一个抽象。服务的示例将是数据转换微服务、计费API等。服务的主要属性是它的URL(其中Kong应该代理流量),它可以被设置为单个字符串或单独指定它的协议、主机、端口和路径。
通过执行下面的命令,将名称为example-servic,地址为url=http://mockbin.org的服务注册到Kong上。
$ curl -i -X POST \
--url http://localhost:8001/services/ \
--data 'name=example-service' \
--data 'url=http://mockbin.org'
执行命令后,返回的结果类似下面的内容:
HTTP/1.1 201 CreatedContent-Type: application/json
Connection: keep-alive
{
"host":"mockbin.org",
"created_at":1519130509,
"connect_timeout":60000,
"id":"92956672-f5ea-4e9a-b096-667bf55bc40c",
"protocol":"http",
"name":"example-service",
"read_timeout":60000,
"port":80,
"path":null,
"updated_at":1519130509,
"retries":5,
"write_timeout":60000}
5.1.2 创建路由
路由实体定义用来匹配客户端请求的规则。每个路由都与一个服务相关联,并且一个服务可能具有与其相关的多个路由。匹配给定路由的每个请求都将被代理到其关联的服务。通过路由和服务的组合(以及它们之间的关注点分离)提供了强大的路由机制,通过这种机制,可以在Kong中定义细粒度入口点,从而实现基础设施的不同上游服务。
$ curl -i -X POST \
--url http://localhost:8001/services/example-service/routes \
--data 'hosts[]=example.com'
返回结果如下所示:
HTTP/1.1 201 CreatedContent-Type: application/json
Connection: keep-alive
{
"created_at":1519131139,
"strip_path":true,
"hosts":[
"example.com"
],
"preserve_host":false,
"regex_priority":0,
"updated_at":1519131139,
"paths":null,
"service":{
"id":"79d7ee6e-9fc7-4b95-aa3b-61d2e17e7516"
},
"methods":null,
"protocols":[
"http",
"https"
],
"id":"f9ce2ed7-c06e-4e16-bd5d-3a82daef3f9d"}
在为服务创建好路由后,Kong就做好对外提供了此服务的准备。
5.1.3 通过Kong转达对于服务的请求
发出以下curl请求,以验证Kong是否正确地将请求转发给服务。注意,缺省情况下,Kong处理端口上的代理请求:8000:
$ curl -i -X GET \
--url http://localhost:8000/ \
--header 'Host: example.com'
成功的响应意味着Kong将http://localhost:8000发出的请求转发到在步骤#1中配置的url(https://mockbin.org),并将返回响应结果。通过在curl请求中定义的头,Kong知道如何做的这一点:
Host: <given host>
5.2 注册API
在此部分将把API添加到Kong层,以让Kong管理API。
5.2.1 使用Admin API注册
通过下面的命令将API (Mockbin) 注册到Kong中:
$ curl -i -X POST \
--url http://localhost:8001/apis/ \
--data 'name=example-api' \
--data 'hosts=example.com' \
--data 'upstream_url=http://mockbin.org'
5.2.2 验证API
注册后返回的信息应该如下所示:
HTTP/1.1 201 CreatedContent-Type: application/json
Connection: keep-alive
{
"created_at": 1488830759000,
"hosts": [
"example.com"
],
"http_if_terminated": false,
"https_only": false,
"id": "6378122c-a0a1-438d-a5c6-efabae9fb969",
"name": "example-api",
"preserve_host": false,
"retries": 5,
"strip_uri": true,
"upstream_connect_timeout": 60000,
"upstream_read_timeout": 60000,
"upstream_send_timeout": 60000,
"upstream_url": "http://mockbin.org"}
5.1.3 通过Kong转发请求
发出以下curl请求,以验证Kong是否正确地将请求转发给服务。注意,缺省情况下,Kong处理端口上的代理请求:8000:
$ curl -i -X GET \
--url http://localhost:8000/ \
--header 'Host: example.com'
成功的响应意味着Kong将http://localhost:8000发出的请求转发到在步骤#1中配置的url(https://mockbin.org),并将返回响应结果。通过在curl请求中定义的头,Kong知道如何做的这一点:
Host: <given host>
6、Admin API
6.1 API Object
API对象描述了一个由Kong公开的API。当使用者从代理端口(Proxy port)调用它时,Kong需要知道如何获取此API。每个API对象必须指定主机(hosts)、uris和方法(method)的一些组合。Kong将把所有对API的请求委托给指定的upstream URL。
{
"created_at": 1488830759000,
"hosts": [
"example.org"
],
"http_if_terminated": false,
"https_only": false,
"id": "6378122c-a0a1-438d-a5c6-efabae9fb969",
"name": "example-api",
"preserve_host": false,
"retries": 5,
"strip_uri": true,
"upstream_connect_timeout": 60000,
"upstream_read_timeout": 60000,
"upstream_send_timeout": 60000,
"upstream_url": "http://httpbin.org"}
6.1.1 注册API
请求地址:/apis/
请求方法:POST
属性 | 描述 |
| API的名称 |
| 以逗号分隔,指向API的域名列表。例如:example.com。至少应该指定主机、uri或方法中的一个。 |
| 以逗号分隔,指向API的uri前缀列表。例如: /my-path。至少应该指定主机、uri或方法中的一个。 |
| 以逗号分隔,指向API的HTTP方法列表。例如: GET,POST。至少应该指定主机、uri或方法中的一个。 |
| 指向API服务器的基本目标URL,这个URL将被用于代理请求。例如: https://example.com. |
| 当通过一个uris前缀匹配一个API时,要从upstream URI中去掉匹配的前缀。默认值:true。 |
| 当通过一个主机域名匹配一个API时,请确保请求主机头被转发到upstream服务。默认值:false,upstream主机头将从配置的upstream_url中提取出来。 |
| 在代理失败的情况下执行的重试次数。默认值是5。 |
| 建立连接到upstream服务的连接超时时间。默认为60000。 |
| The timeout in milliseconds between two successive write operations for transmitting a request to your upstream service Defaults to |
| The timeout in milliseconds between two successive read operations for transmitting a request to your upstream service Defaults to |
| 如果希望仅使用HTTPS提供API(默认情况下是8443),那么就可以启用该参数。默认值:false。 |
| 在执行HTTPS通信时,考虑一下X-Forwarded-Proto header。默认值: false |
6.1.2 检索API
请求地址:/apis/{name or id}
请求方法:GET
属性 | 描述 |
name or id(必填) | 要检索的API的唯一标识符或名称。 |
6.1.3 API列表
请求地址:/apis/
请求方法:GET
属性 | 描述 |
id(可选) | 基于api id字段的过滤器。 |
name(可选) | 基于api name字段的过滤器。 |
upstream_url(可选) | 基于api upstream_url字段的过滤器。 |
retries(可选) | 基于api retries字段的过滤器。 |
offset(可选) | 用于分页的游标。偏移量是定义列表中的位置的对象标识符。 |
size(可选,默认是100) | 每个页面返回的对象数量的限制。 |
6.1.4 更新API
请求地址:/apis/{name or id}
请求方法:GET
属性 | 描述 |
| The unique identifier or the name of the API to delete |
6.1.5 删除API
请求地址:/apis/{name or id}
请求方法:DELETE
PATH参数:
属性 | 描述 |
name or id required | 删除API的名称或唯一的标识符。 |
6.2 插件对象(Plugin Object)
插件实体表示将在HTTP请求/响应生命周期期间执行的插件配置。通过插件,可以为服务添加功能,例如身份验证或速率限制。可以通过访问Kong Hub找到需要的插件,以及有关如何安装和值的更多信息。当添加一个插件配置到服务后,客户端向该服务发出的每个请求都将会运行添加的插件。如果需要为特定消费者将插件调整为不同的值,可以通过指定 consumer_id值来实现:
{
"id": "4d924084-1adb-40a5-c042-63b19db421d1",
"service_id": "5fd1z584-1adb-40a5-c042-63b19db49x21",
"consumer_id": "a3dX2dh2-1adb-40a5-c042-63b19dbx83hF4",
"name": "rate-limiting",
"config": {
"minute": 20,
"hour": 500
},
"enabled": true,
"created_at": 1422386534}
6.2.1 优先级
插件将始终只被运行一次,即每次请求只运行一次。但是它所运行的配置取决于它所配置的实体。当插件应用于具有不同配置的不同实体时,存在一个优先顺序来运行插件。经验法则是:插件越具体,所配置的实体数量越多,优先级越高。
当一个插件被多次配置时,完整优先纪顺序是:
插件的配置组合:路由(Route),服务(Service)和消费者(Consumer)。(消费者意味着必须对请求进行身份验证)。
在Route和Consumer的组合上配置的插件。(消费者意味着必须对请求进行身份验证)。
在服务和使用者的组合上配置的插件。(消费者意味着必须对请求进行身份验证)。
在路由和服务的组合上配置的插件。
在Consumer上配置的插件。(消费者意味着必须对请求进行身份验证)。
在路由上配置的插件。
在服务上配置的插件。
配置为全局运行的插件。
示例:如果rate-limiting插件应用了两次(具有不同的配置):对于服务(插件配置A)和对于消费者(插件配置B),则对此消费者进行身份验证的请求将运行插件配置B并忽略A.但是,请求不认证此消费者将回退到运行插件配置A.请注意,如果禁用配置B(其enabled
标志设置为false
),配置A将应用于否则将匹配配置B的请求。
6.2.2 添加插件
可以通过下面的几种方式添加插件:
对于每个服务/路由和消费者。不要设置consumer_id,而是设置service_id或route_id。
适用于每个服务/路由和特定消费者。只有设定consumer_id。
适用于每个消费者和特定服务。仅设置service_id(警告:某些插件只允许设置route_id)
对于每个消费者和特定的路由。仅设置route_id(警告:某些插件只允许设置service_id)
对于特定的服务/路由和消费者。设置service_id/route_id和consumer_id。
请注意,并非所有插件都允许指定consumer_id。
6.2.2.1 Request Body
属性 | 描述 |
name | 要添加的插件的名称。目前,插件必须分别安装在每个Kong实例中。 |
consumer_id | 使用者的唯一标识符,用于覆盖传入请求中此特定使用者的现有设置。 |
config.{property} | 插件的配置属性,可以在Kong Hub的插件文档页面找到。 |
enabled | 是否应用插件。默认值:true。 |
Response
HTTP 201 Created
{
"id": "4d924084-1adb-40a5-c042-63b19db421d1",
"service_id": "5fd1z584-1adb-40a5-c042-63b19db49x21",
"consumer_id": "a3dX2dh2-1adb-40a5-c042-63b19dbx83hF4",
"name": "rate-limiting",
"config": {
"minute": 20,
"hour": 500
},
"enabled": true,
"created_at": 1422386534}
参考资料
1.《Route Object》地址:https://docs.konghq.com/0.13.x/admin-api/#route-object;
2.《Configuring a Service》地址:https://docs.konghq.com/0.14.x/getting-started/configuring-a-service/
3.《Kong and Kong Enterprise on Kubernetes》地址:https://docs.konghq.com/install/kubernetes/?_ga=2.256537099.1475189429.1544400620-1563374863.1537379250
作者简介:
季向远,北京神舟航天软件技术有限公司。本文版权归原作者所有。
K8S培训推荐
Kubernetes线下实战培训,采用3+1+1新的培训模式(3天线下实战培训,1年内可免费再次参加,每期前10名报名,可免费参加价值3600元的线上直播班;),资深一线讲师,实操环境实践,现场答疑互动,培训内容覆盖:Docker方面:Docker架构、镜像、数据存储、网络、以及最佳实践。Kubernetes实战内容,Kubernetes设计、Pod、常用对象操作,Kuberentes调度系统、QoS、Helm、网络、存储、CI/CD、日志监控等。
北京:5月10-12日
报名链接:https://www.bagevent.com/event/2376547
上海:5月17-19日
报名链接:https://www.bagevent.com/event/2409655
深圳:5月24-26日
报名链接:https://www.bagevent.com/event/2409699
推荐阅读